import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Class performing long division.
 * Displays dividend, denominator, result,
 * intermediate division and modulo.
 */
public class Division {
    /**
     *Class fields. Dividend, denominator, result, modulo,
     * indentation at the intermediate division, intermediate modulo,
     * variable to go to print the intermediate division.
     * An array of dividend's characters.
     */
    private static Integer dividend=0;
    private static Integer denominator=1;
    private static String intend = "";
    private static String rest = "";

    public static void main(String[] args) throws IOException {
        inputData();
        printDivision();
    }

    /**
     * A method to input dividend and denominator
     * and calculation of the result and modulo.
     * @throws IOException
     */
    private static void inputData() throws IOException {
        while(true){
            try{
                System.out.println("Введите делимое и делитель");
                BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
                dividend = scanInt(reader);
                denominator = scanInt(reader);
                if (denominator != 0){
                    break;
                } else {
                    System.out.println("Нельзя делить на 0, попробуйте ещё раз.");
                }
            } catch (NumberFormatException e){
                System.out.println("Введены некодектные данные, попробуйте еще раз.");
            }
        }
    }

    /**
     * A method read string from keyboard.
     * @param reader
     * @return
     * @throws IOException
     */
    private static int scanInt(BufferedReader reader) throws IOException {
        String stringDividend = reader.readLine();
        Integer dividend = Integer.parseInt(stringDividend);
        return dividend;
    }

    /**
     * The method for displaying information about the division on the screen.
     * The method checks that more dividend or denominator
     * and depending on this, performs a determination unit.
     * The method displays the first two lines on a particular algorithm
     * as input information string containing, and then print modulo.
     */
    private static void printDivision(){
        char[] dividendToCharArr = convertDividendToCharacterArray(dividend);
        boolean switcher = true;
        if (Math.abs(dividend) < Math.abs(denominator)){
            printIfDividendLessThenDenominator();
        }
        for (int i = 0; i < dividendToCharArr.length; i++){
            String divisorString = String.format("%1$s%2$s", rest, dividendToCharArr[i]);
            Integer divisor = Integer.parseInt(divisorString);
            if (Math.abs(divisor) < Math.abs(denominator)){
                rest = divisorString;
            } else {
                switcher = printIfDividendBiggerThenDenominator(divisor, switcher);
            }
        }
        printModulo();
    }

    private static char[] convertDividendToCharacterArray(Integer dividend){
        if (dividend < 0){
            //Возврвщаем массив без минуса.
            intend += " ";
            return dividend.toString().substring(1).toCharArray();
        }
        return dividend.toString().toCharArray();
    }

    /**
     * The method for displaying division when dividend
     * bigger then denominator.
     * @param divisor
     * @param switcher
     * @return
     */
    private static boolean
    printIfDividendBiggerThenDenominator(Integer divisor, boolean switcher){
        if (switcher){
            printTwoFirstRows(divisor);
            switcher = false;
        }else {
            printIntermediateDivision(divisor);
        }
        return switcher;
    }

    /**
     * The method for displaying the first two lines.
     * @param divisor
     */
    private static void printTwoFirstRows(Integer divisor){
        Integer restOfIntermediateDivision = divisor % denominator;
        Integer deductedOfIntermediateDivision =
                divisor - restOfIntermediateDivision;
        if (restOfIntermediateDivision == 0)
            intend += " ";
        String s1 = String.format("_%d ", dividend);
        System.out.printf("%s%d%c", s1, denominator, '\n');
        String s2 = String.format(" %d", deductedOfIntermediateDivision);
        printSpace(divisor.toString().length(),
                deductedOfIntermediateDivision.toString().length());
        if (dividend < 0) {
            System.out.print(" ");
        }
        System.out.print(s2);
        printSpace(s1.length(), s2.length());
        System.out.println(dividend / denominator);
        rest = restOfIntermediateDivision.toString();
        System.out.print(" ");
        printLine(denominator.toString().length());
        increaseIntend(divisor.toString().length(),
                restOfIntermediateDivision.toString().length());
    }

    /**
     * The method to display the intermediate division.
     * @param divisor
     */
    private static void printIntermediateDivision(Integer divisor){
        Integer restOfIntermediateDivision = divisor%denominator;
        Integer deductedOfIntermediateDivision =
                divisor - restOfIntermediateDivision;
        System.out.printf("%1$s_%2$s%3$s", intend, divisor, '\n');
        System.out.printf("%s ", intend);
        printSpace(divisor.toString().length(),
                deductedOfIntermediateDivision.toString().length());
        System.out.println(deductedOfIntermediateDivision);
        System.out.printf("%s ",intend);
        printLine(divisor.toString().length());
        rest = restOfIntermediateDivision.toString();
        increaseIntend(divisor.toString().length(),
                restOfIntermediateDivision.toString().length());
        if (restOfIntermediateDivision == 0) intend += " ";
    }

    /**
     * The method to display result and modulo.
     */
    private static void printModulo(){
        Integer modulo = dividend % denominator;
        printSpace(dividend.toString().length() + 1,
                modulo.toString().length());
        System.out.println(dividend % denominator);
    }

    /**
     * Method to display the result if the denominator is greater than the dividend.
     */
    private static void printIfDividendLessThenDenominator(){
        System.out.printf("_%d %d%c", dividend, denominator, '\n');
        printSpace(dividend.toString().length(), 0);
        System.out.printf("0 %d%c", dividend / denominator, '\n');
    }

    /**
     * The method for printing intend.
     * @param firstArgument
     * @param secondArgument
     */
    private static void printSpace(int firstArgument, int secondArgument){
        for (int i = 0; i < firstArgument - secondArgument; i++){
            System.out.print(" ");
        }
    }

    /**
     * The method for printing lines.
     * @param lineLength
     */
    private static void printLine(int lineLength){
        for (int i = 0; i < lineLength; i++){
            System.out.print('_');
        }
        System.out.println("");
    }

    /**
     * Method for increasing intend.
     * @param firstArgument
     * @param secondArgument
     */
    private static void increaseIntend(int firstArgument, int secondArgument){
        for (int i = 0; i < firstArgument - secondArgument; i++){
            intend += " ";
        }
    }
}